<script setup lang="tsx">
import { computed, reactive, ref, unref } from 'vue'
import { createMenuApi, deleteMenuApi, getMenuPageApi, updateMenuApi } from '@/api/menu'
import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n'
import { Table, TableColumn } from '@/components/Table'
import { ElTag } from 'element-plus'
import { Icon } from '@/components/Icon'
import { Search } from '@/components/Search'
import { FormSchema } from '@/components/Form'
import { ContentWrap } from '@/components/ContentWrap'
import Write from './components/Write.vue'
import Detail from './components/Detail.vue'
import { Dialog } from '@/components/Dialog'
import { BaseButton } from '@/components/Button'
import { listToTree } from '@/utils/tree'
import { Log } from '@/utils/logError'
import { CalculateCellWidth } from '@/utils/calculateCellWidth'

const { t } = useI18n()

const { tableRegister, tableState, tableMethods } = useTable({
  fetchDataApi: async () => {
    const { currentPage, pageSize } = tableState
    const { data, pagination } = await getMenuPageApi({
      pageNum: unref(currentPage) || 1,
      pageSize: unref(pageSize) || 10,
      ...unref(searchParams)
    })
    return {
      list: listToTree(data || [], { pid: 'parentId' }),
      total: pagination?.total || 0
    }
  },
  fetchDelApi: async () => {
    await deleteMenuApi(currentRow.value.id)
    return true
  }
})

const { dataList, loading } = tableState
const { getList, delList } = tableMethods

const actionWidth = computed(() =>
  CalculateCellWidth([
    { permission: 'menus:update', width: 86 },
    { permission: 'menus:detail', width: 86 },
    { permission: 'menus:delete', width: 86 }
  ])
)

const tableColumns = reactive<TableColumn[]>([
  {
    field: 'index',
    label: t('common.tableIndex'),
    type: 'index'
  },
  {
    field: 'title',
    label: t('menu.title'),
    slots: {
      default: ({ row }) => {
        return <>{t(row.title)}</>
      }
    }
  },
  {
    field: 'name',
    label: t('menu.menuName')
  },
  {
    field: 'icon',
    label: t('menu.icon'),
    slots: {
      default: ({ row }) => {
        const icon = row.icon
        if (icon) {
          return (
            <>
              <Icon icon={icon} />
            </>
          )
        } else {
          return null
        }
      }
    }
  },
  {
    field: 'component',
    label: t('menu.component')
  },
  {
    field: 'type',
    label: t('menu.menuType'),
    slots: {
      default: ({ row }) => {
        const { type } = row
        const mapper = {
          directory: t('menu.topDirectory'),
          menu: t('menu.menu'),
          api: t('menu.api'),
          button: t('menu.button')
        }
        return <>{<ElTag>{mapper[type]}</ElTag>}</>
      }
    }
  },
  {
    field: 'path',
    label: t('menu.path')
  },
  {
    field: 'status',
    label: t('menu.status'),
    slots: {
      default: ({ row }) => {
        return (
          <>
            <ElTag type={row.status ? 'success' : 'danger'}>
              {row.status ? t('common.enable') : t('common.disable')}
            </ElTag>
          </>
        )
      }
    }
  },
  {
    field: 'action',
    label: t('common.action'),
    width: actionWidth.value,
    slots: {
      default: (data: any) => {
        const row = data.row
        return (
          <>
            <BaseButton
              type="primary"
              v-prem={{ value: 'menus:update' }}
              onClick={() => action(row, 'edit')}
            >
              {t('common.edit')}
            </BaseButton>
            <BaseButton
              type="success"
              v-prem={{ value: 'menus:detail' }}
              onClick={() => action(row, 'detail')}
            >
              {t('common.detail')}
            </BaseButton>
            <BaseButton
              type="danger"
              v-prem={{ value: 'menus:delete' }}
              onClick={() => action(row, 'delete')}
            >
              {t('common.del')}
            </BaseButton>
          </>
        )
      }
    }
  }
])

const searchSchema = reactive<FormSchema[]>([
  {
    field: 'name',
    label: t('menu.menuName'),
    component: 'Input'
  },
  {
    field: 'status',
    label: t('menu.menuStatus'),
    component: 'Select',
    componentProps: {
      options: [
        {
          label: t('common.enable'),
          value: true
        },
        {
          label: t('common.disable'),
          value: false
        }
      ]
    }
  }
])

const searchParams = ref<{
  name: string
  title: string
  status: boolean
}>({
  title: '',
  name: '',
  status: true
})
const setSearchParams = (data: any) => {
  searchParams.value = data
  getList()
}

const dialogVisible = ref(false)
const dialogTitle = ref('')

const currentRow = ref()
const actionType = ref('')

const writeRef = ref<ComponentRef<typeof Write>>()

const saveLoading = ref(false)

const action = (row: any, type: string) => {
  dialogTitle.value = t(type === 'edit' ? 'common.edit' : 'common.detail')
  actionType.value = type
  currentRow.value = row
  type !== 'delete' ? (dialogVisible.value = true) : delList(1)
}

const AddAction = () => {
  dialogTitle.value = t('common.add')
  currentRow.value = undefined
  dialogVisible.value = true
  actionType.value = 'add'
}

const menuSave = async () => {
  try {
    const write = unref(writeRef)
    const formData = (await write?.submit()) as any
    if (!formData) return
    const deleteKeys = ['children', 'parentName', 'createdAt', 'updatedAt']
    deleteKeys.forEach((key) => {
      delete formData[key]
    })
    saveLoading.value = true
    actionType.value === 'add' ? await createMenuApi(formData) : await updateMenuApi(formData)
    await getList()
    saveLoading.value = false
    dialogVisible.value = false
  } catch (error) {
    Log.error('menuSave', error)
  }
}
</script>

<template>
  <ContentWrap v-prem="'menus:page'">
    <Search :schema="searchSchema" @reset="setSearchParams" @search="setSearchParams" />
    <div class="mb-10px">
      <BaseButton type="primary" v-prem="'menus:create'" @click="AddAction">
        {{ t('common.add') }}
      </BaseButton>
    </div>
    <Table
      :columns="tableColumns"
      default-expand-all
      node-key="id"
      :data="dataList"
      :loading="loading"
      @register="tableRegister"
    />
  </ContentWrap>

  <Dialog v-model="dialogVisible" :title="dialogTitle">
    <Detail v-if="actionType === 'detail'" :current-row="currentRow" />
    <Write v-else ref="writeRef" :current-row="currentRow" />

    <template #footer>
      <BaseButton
        v-if="actionType !== 'detail'"
        type="primary"
        v-prem="['menus:create', 'menus:update']"
        :loading="saveLoading"
        @click="menuSave"
      >
        {{ t('common.save') }}
      </BaseButton>
      <BaseButton @click="dialogVisible = false">{{ t('common.close') }}</BaseButton>
    </template>
  </Dialog>
</template>
